/*
 * @Author: Jiarun
 * @Date: 2021-06-05 18:39:29
 * @LastEditors: Jiarun
 * @LastEditTime: 2021-06-08 08:29:47
 * @Description: 
 */
 /* Includes ------------------------------------------------------------------*/
#include "es_tim.h"
#include "es_gpio.h"

/**
 * @description: 定时器基本配置，仅在当前文件调用，无需关心
 * @param {TIM_TypeDef} *TIMx	使用的定时器
 * @param {uint16_t} psc	预分频值
 * @param {uint16_t} arr	自动重装载值
 * @return None
 */
void TimeBaseInit(TIM_TypeDef *TIMx, uint16_t psc, uint16_t arr)
{
	TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;

	RCC_APB1PeriphClockCmd(1 << ((uint32_t)TIMx >> 10), ENABLE); //时钟使能

	TIM_TimeBaseStructure.TIM_Period = arr - 1;					//设置在下一个更新事件装入活动的自动重装载寄存器周期的值
	TIM_TimeBaseStructure.TIM_Prescaler = psc - 1;				//设置TIMx时钟频率的预分频值
	TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;		//设置时钟分割
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
	TIM_TimeBaseInit(TIMx, &TIM_TimeBaseStructure);				//根据指定的参数初始化TIMx的时间基数单位
}

/**
 * @description: 初始化定时器中断 *注意：仅适用于定时器2 - 定时器4
 * @param {TIM_TypeDef} *TIMx	使用的定时器
 * @param {uint16_t} psc		预分频值
 * @param {uint16_t} arr		自动重装载值
 * @param {uint8_t} Preemp	抢占优先级
 * @param {uint8_t} Sub			响应优先级
 * @return None
 * @Sample tim_init(TIM3, 7200, 5000, 2, 2);	//TIM3 中断周期 500ms，抢占优先级与响应优先级均为 2
 */
void tim_init(TIM_TypeDef *TIMx, uint16_t psc, uint16_t arr, uint8_t Preemp, uint8_t Sub)
{

	NVIC_InitTypeDef NVIC_InitStructure;

	TimeBaseInit(TIMx, psc, arr);

	TIM_ITConfig(TIMx, TIM_IT_Update, ENABLE); //使能指定的TIM中断,允许更新中断
	//中断优先级NVIC设置
	NVIC_InitStructure.NVIC_IRQChannel = ((uint32_t)TIMx >> 10) + 28; //TIM中断
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = Preemp;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = Sub;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure); //初始化NVIC寄存器

	TIM_Cmd(TIMx, ENABLE); //使能TIMx
}

/**
 * @description: 配置定时器 PWM 输出		* 输出频率 = SYSCLK / psc / arr | 占空比 = pulse / arr *
 * @param {TIM_TypeDef} *TIMx	使用的定时器
 * @param {uint16_t} psc		预分频值
 * @param {uint16_t} arr		自动重装载值
 * @param {uint16_t} pulse	比较寄存器脉冲值
 * @param {uint8_t} using_ch	启用的 TIM 通道，using_ch 的低四位对应 TIM_CH1 - TIM_CH4，1启用 0禁用
 * @return None
 * @Sample	pwm_init(TIM3, 72, 100, 50, 0x3);	//TIM3 的 CH1 和 CH2 输出频率为 10kHz 占空比为 50% 的方波
 */
void pwm_init(TIM_TypeDef *TIMx, uint16_t psc, uint16_t arr, uint16_t pulse, uint8_t using_ch)
{
	TIM_OCInitTypeDef TIM_OCInitStructure;
	GPIO_TypeDef *GPIOx;
	uint16_t CH_Pin, CH1_Pin;

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);

	if (TIM2 == TIMx)
	{
		GPIOx = GPIOA;
		CH1_Pin = GPIO_Pin_0;
	}
	else if (TIM4 == TIMx)
	{
		GPIOx = GPIOB;
		CH1_Pin = GPIO_Pin_6;
	}

	if (TIM3 == TIMx)
	{
		if (using_ch & 0xC)
		{
			GPIOx = GPIOA;
			if (using_ch & 0x8)
				CH_Pin |= GPIO_Pin_6;
			if (using_ch & 0x4)
				CH_Pin |= GPIO_Pin_7;
			gpio_init(GPIOx, CH_Pin, GPIO_Mode_AF_PP);
		}
		if (using_ch & 0x3)
		{
			GPIOx = GPIOB;
			CH_Pin = 0;
			if (using_ch & 0x2)
				CH_Pin |= GPIO_Pin_0;
			if (using_ch & 0x1)
				CH_Pin |= GPIO_Pin_1;
			gpio_init(GPIOx, CH_Pin, GPIO_Mode_AF_PP);
		}
	}
	else
	{
		if (using_ch & 0x1)
			CH_Pin |= CH1_Pin;
		if (using_ch & 0x2)
			CH_Pin |= CH1_Pin << 1;
		if (using_ch & 0x4)
			CH_Pin |= CH1_Pin << 2;
		if (using_ch & 0x8)
			CH_Pin |= CH1_Pin << 3;

		gpio_init(GPIOx, CH_Pin, GPIO_Mode_AF_PP);
	} /* end if */

	/* Time base configuration */
	TimeBaseInit(TIMx, psc, arr);

	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
	TIM_OCInitStructure.TIM_Pulse = pulse;
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;

	if (using_ch & 0x1)
		TIM_OC1Init(TIMx, &TIM_OCInitStructure);
	if (using_ch & 0x2)
		TIM_OC2Init(TIMx, &TIM_OCInitStructure);
	if (using_ch & 0x4)
		TIM_OC3Init(TIMx, &TIM_OCInitStructure);
	if (using_ch & 0x8)
		TIM_OC4Init(TIMx, &TIM_OCInitStructure);

	/** 输出比较预装载使能
  * 禁止预装载功能，新写入的数值立即起作用
	* 使能预装载功能，预装载值在更新事件到来时被加载至当前寄存器中
	*/
	//  TIM_OC1PreloadConfig(TIMx, TIM_OCPreload_Enable);
	TIM_ARRPreloadConfig(TIMx, ENABLE);
	/* TIM enable counter */
	TIM_Cmd(TIMx, ENABLE);
}

/**
 * @description: 设置捕获比较寄存器的值，以改变 PWM 的占空比
 * @param {TIM_TypeDef} *TIMx	目标定时器
 * @param {uint8_t} channel		目标通道
 * @param {uint16_t} pulse		待装入捕获比较寄存器值
 * @return None
 * @Sample set_pulse(TIM3, 1, 20);
 */
void set_pulse(TIM_TypeDef *TIMx, uint8_t channel, uint16_t pulse)
{
	switch (pulse)
	{
	case 1:
		TIMx->CCR1 = pulse;
		break;
	case 2:
		TIMx->CCR2 = pulse;
		break;
	case 3:
		TIMx->CCR3 = pulse;
		break;
	case 4:
		TIMx->CCR4 = pulse;
		break;
	default:
		break;
	}
}
